pub use embassy::executor::task;
use embassy::executor::{Executor, SpawnToken, Spawner};
use embassy::time::{Duration, Timer};
use embassy::util::Forever;
use embassy_nrf::{interrupt, pac, rtc};

static RTC: Forever<rtc::RTC<pac::RTC1>> = Forever::new();
static ALARM: Forever<rtc::Alarm<pac::RTC1>> = Forever::new();
static EXECUTOR: Forever<Executor> = Forever::new();
static SPAWNER: Forever<Spawner> = Forever::new();

pub fn start(p: pac::RTC1, init: impl FnOnce(Spawner)) -> ! {
    let rtc = RTC.put(rtc::RTC::new(p, interrupt::take!(RTC1)));
    rtc.start();

    unsafe { embassy::time::set_clock(rtc) };

    let alarm = ALARM.put(rtc.alarm0());
    let executor = EXECUTOR.put(Executor::new());
    executor.set_alarm(alarm);
    executor.run(|spawner| {
        SPAWNER.put(spawner.clone());
        init(spawner);
    });
}

pub fn spawn<F>(token: SpawnToken<F>) {
    let result = unsafe { SPAWNER.steal() }.spawn(token);
    if let Err(e) = result {
        log::warn!("thread err: {:?}.", e);
    }
}

pub fn sleep_ms(ms: u64) -> Timer {
    Timer::after(Duration::from_millis(ms))
}
